<template>
  <div class="common-uploader" :class="{ 'flex': multiple }">
    <div v-if="imgUrl" class="img_wrapper" :style="{ 'width': wrapperWidth, 'height': wrapperHeight }">
      <img v-if="imgUrl" :src="'https://img.tingxiangzu.com/'+ imgUrl" class="w-100 h-100">
      <el-image-viewer v-if="showViewer" :on-close="closeViewer" :url-list="['https://img.tingxiangzu.com/' + imgUrl]" />
      <p class="mask_tool">
        <span style="display: inline-block;width: 50px;" class="flex-1 text-center pointer" @click.stop="showViewer = true">查看</span>
        <el-divider v-if="!hideDelete" direction="vertical" />
        <span style="display: inline-block;width: 50px;" v-if="!hideDelete" class="flex-1 text-center pointer" @click.stop="delImg">删除</span>
      </p>
    </div>
    <div v-if="multiple" class="flex flex-wrap mul_list">
      <template v-if="fileList.length > 0">
        <el-image-viewer v-if="showViewer" :on-close="closeViewer" :url-list="['https://img.tingxiangzu.com/' + showUrl]" />
        <template v-if="!sort">
          <div v-for="(item, index) in fileList" :key="item" class="inline-block img_wrapper" :style="{ 'width': wrapperWidth, 'height': wrapperHeight }">
            <img v-if="item" :src="'https://img.tingxiangzu.com/' + item" class="w-100 h-100">
            <!-- <el-image-viewer
              v-if="showViewer"
              :on-close="closeViewer"
              :url-list="[$globalObj.imgBaseUrl+item]"
            /> -->
            <p class="mask_tool">
              <span class="flex-1 text-center pointer" @click.stop="previewImg(item)">查看</span>
              <el-divider v-if="!hideDelete" direction="vertical" />
              <span v-if="!hideDelete" class="flex-1 text-center pointer" @click.stop="delImg(index)">删除</span>
            </p>
          </div>
        </template>
        <vuedraggable v-else v-model="sortList" class="draggable-container">
          <transition-group>
            <div v-for="(item, index) in sortList" :key="item" class="inline-block img_wrapper" :style="{ 'width': wrapperWidth, 'height': wrapperHeight }">
              <img v-if="item" :src="'https://img.tingxiangzu.com/' + item" class="w-100 h-100">
              <!-- <el-image-viewer
                v-if="showViewer"
                :on-close="closeViewer"
                :url-list="[$globalObj.imgBaseUrl+item]"
              /> -->
              <p class="mask_tool">
                <span class="flex-1 text-center pointer" @click.stop="previewImg(item)">查看</span>
                <el-divider v-if="!hideDelete" direction="vertical" />
                <span v-if="!hideDelete" class="flex-1 text-center pointer" @click.stop="delImg(index)">删除</span>
              </p>
            </div>
          </transition-group>
        </vuedraggable>
      </template>
      <el-upload v-if="fileList.length < maxNum" ref="upload" action="string" :accept="accept ? accept : 'image/*'" :show-file-list="false" :http-request="httpRequest" :before-upload="beforeUpload">
        <el-button v-if="showType === 'button'" size="small" type="primary">点击上传</el-button>
        <div v-if="showType === 'photo'" :style="{ 'width': photoWidth + 'px', 'height': photoHeight + 'px' }" class="flex flex-column align-center justify-center photo_wrapper">
          <i class="el-icon-plus" />
          <span>上传图片</span>
        </div>
        <div v-if="tip" slot="tip" class="el-upload__tip">{{ tip }}<br v-if="subTip">{{ subTip }}</div>
      </el-upload>
    </div>
    <el-upload v-if="!multiple && !imgUrl" ref="upload" action="string" :accept="accept ? accept : 'image/*'" :show-file-list="false" :http-request="httpRequest" :before-upload="beforeUpload">
      <el-button v-if="showType === 'button'" size="small" type="primary">点击上传</el-button>
      <div v-if="showType === 'photo'" :style="{ 'width': photoWidth + 'px', 'height': photoHeight + 'px' }" class="flex flex-column align-center justify-center photo_wrapper">
        <i class="el-icon-plus" />
        <span>上传图片</span>
      </div>
      <div v-if="tip" slot="tip" class="el-upload__tip">{{ tip }}<br v-if="subTip">{{ subTip }}</div>
    </el-upload>
    <el-dialog :width="dialogWidth" title="图片剪裁" :visible.sync="dialogVisible" append-to-body>
      <div class="m-auto cropper" :style="{ 'width': cropperWidth, 'height': cropperHeight }">
        <vueCropper ref="cropper" :img="option.img" :output-type="outputType" :output-size="option.outputSize" :info="option.info" :can-scale="option.canScale" :auto-crop="option.autoCrop" :auto-crop-width="autoCropWidth" :auto-crop-height="autoCropHeight" :fixed="fixScale" :fixed-box="fixedBox" :fixed-number="option.fixedNumber" :enlarge="enlarge" />
      </div>
      <div slot="footer" class="dialog-footer">
        <el-button size="small" type="primary" @click="cancelCrop">直接上传</el-button>
        <el-button size="small" type="primary" :loading="loading" @click="finish">裁剪</el-button>
      </div>
    </el-dialog>
  </div>
</template>

<script>
import { upload } from '@/api/index'
import { VueCropper } from 'vue-cropper'
import ElImageViewer from 'element-ui/packages/image/src/image-viewer'
import vuedraggable from 'vuedraggable'
export default {
  components: { VueCropper, ElImageViewer, vuedraggable },
  props: {
    dialogWidth: {
      type: String,
      default: '400px'
    },
    showType: {
      type: String,
      default: 'button'
    },
    accept: {
      type: String,
      default: ''
    },
    tip: {
      type: String,
      default: ''
    },
    subTip: {
      type: String,
      default: ''
    },
    fileSize: {
      type: String,
      default: '2M'
    },
    imgWidth: {
      type: Number,
      default: 0
    },
    imgHeight: {
      type: Number,
      default: 0
    },
    wrapperWidth: {
      type: String,
      default: 'auto'
    },
    wrapperHeight: {
      type: String,
      default: ''
    },
    alwaysCrop: {
      type: Boolean,
      default: false
    },
    fixedBox: {
      type: Boolean,
      default: true
    },
    autoCropWidth: {
      type: Number,
      default: 0
    },
    autoCropHeight: {
      type: Number,
      default: 0
    },
    fixScale: {
      type: Boolean,
      default: false
    },
    cropperWidth: {
      type: String,
      default: '100%'
    },
    cropperHeight: {
      type: String,
      default: ''
    },
    photoWidth: {
      type: Number,
      default: 95
    },
    photoHeight: {
      type: Number,
      default: 95
    },
    initVal: {},
    enlarge: {
      type: Number,
      default: 1
    },
    minWidth: {
      type: Number,
      default: 0
    },
    minHeight: {
      type: Number,
      default: 0
    },
    multiple: {
      type: Boolean,
      default: false
    },
    maxNum: {
      type: Number,
      default: 10
    },
    sort: {
      type: Boolean,
      default: false
    },
    isSquare: {
      type: Boolean,
      default: false
    },
    hideDelete: {
      type: Boolean,
      default: false
    }
  },
  data() {
    return {
      dialogVisible: false,
      // 裁剪组件的基础配置option
      option: {
        img: '', // 裁剪图片的地址
        info: true, // 裁剪框的大小信息
        outputSize: 0.8, // 裁剪生成图片的质量
        canScale: true, // 图片是否允许滚轮缩放
        autoCrop: true, // 是否默认生成截图框
        full: false, // 是否输出原图比例的截图
        canMoveBox: true, // 截图框能否拖动
        original: true, // 上传图片按照原始比例渲染
        infoTrue: true, // true 为展示真实输出图片宽高 false 展示看到的截图框宽高
        canMove: true
      },
      loading: false,
      fileInfo: null,
      showViewer: false,
      sortList: [],
      showUrl: ''
    }
  },
  computed: {
    outputType() {
      if ((this.accept && this.accept.indexOf('png') > -1) || this.alwaysCrop) {
        return 'png'
      } else {
        return 'jpeg'
      }
    },
    imgUrl() {
      return this.multiple ? '' : (this.initVal ? this.initVal : '')
    },
    fileList() {
      return this.multiple ? (this.initVal ? this.initVal : []) : []
    }
  },
  watch: {
    sortList: {
      handler(val) {
        if (this.sort) {
          this.$emit('setVal', val, 'sort')
        }
      },
      deep: true
    }
  },
  mounted() {
    this.$nextTick(() => {
      if (this.multiple) {
        this.sortList = [...this.fileList]
      }
    })
  },
  methods: {
    previewImg(url) {
      this.showUrl = url
      this.$nextTick(() => {
        this.showViewer = true
      })
    },
    // 删除
    delImg(index) {
      if (this.multiple) {
        this.$emit('setVal', index, 'del')
      } else {
        this.$emit('setVal', '')
      }
    },
    // 关闭预览
    closeViewer() {
      this.showViewer = false
    },
    // 直接上传
    cancelCrop() {
      if (this.imgWidth || this.imgHeight || this.minWidth || this.minHeight || this.isSquare) {
        this.sizeCheck(this.fileInfo).then(res => {
          if (res) {
            const fd = new FormData()
            fd.append('file', this.fileInfo)
            upload(fd).then(res => {
              if (this.multiple) {
                this.$emit('setVal', res.image, 'add')
              } else {
                this.$emit('setVal', res.image)
              }
              this.dialogVisible = false
            })
          }
        })
      } else {
        const fd = new FormData()
        fd.append('file', this.fileInfo)
        upload(fd).then(res => {
          if (this.multiple) {
            this.$emit('setVal', res.image, 'add')
          } else {
            this.$emit('setVal', res.image)
          }
          this.dialogVisible = false
        })
      }
    },
    // 裁剪
    finish() {
      this.loading = true
      this.$refs.cropper.getCropBlob((data) => {
        const file = new window.File([data], this.fileInfo.name, { type: data.type })
        if (this.imgWidth || this.imgHeight || this.minWidth || this.minHeight || this.isSquare) {
          this.sizeCheck(file).then(res => {
            if (res) {
              const fd = new FormData()
              fd.append('file', file)
              upload(fd).then(res => {
                this.loading = false
                if (this.multiple) {
                  this.$emit('setVal', res.image, 'add')
                } else {
                  this.$emit('setVal', res.image)
                }
                this.dialogVisible = false
              }).catch(error => {
								console.log(error);
                this.loading = false
              })
            }
          }).catch(() => {
            this.loading = false
          })
        } else {
          const fd = new FormData()
          fd.append('file', file)
          upload(fd).then(res => {
            this.loading = false
            if (this.multiple) {
              this.$emit('setVal', res.image, 'add')
            } else {
              this.$emit('setVal', res.image)
            }
            this.dialogVisible = false
          }).catch(error => {
						console.log(error);
            this.loading = false
          })
        }
      })
    },
    async sizeCheck(file) {
      const that = this
      let flag, minWValid, minHValid, imgWValid, imgHValid
      const isSize = await new Promise(function(resolve, reject) {
        const _URL = window.URL || window.webkitURL
        const img = new Image()
        img.onload = function() {
          minWValid = that.minWidth ? img.width >= that.minWidth : true
          minHValid = that.minHeight ? img.height >= that.minHeight : true
          imgWValid = that.imgWidth ? img.width === that.imgWidth : true
          imgHValid = that.imgHeight ? img.height === that.imgHeight : true
          flag = that.isSquare ? img.width === img.height : true
          minWValid && minHValid && imgWValid && imgHValid && flag ? resolve() : reject()
        }
        img.src = _URL.createObjectURL(file)
      }).then(() => {
        return file
      }, () => {
        if (!flag) {
          that.$message.error('图片要求为正方形！')
        } else if (!minWValid) {
          that.$message.error('图片尺寸要求宽度最小为' + that.minWidth + 'px！')
        } else if (!minHValid) {
          that.$message.error('图片尺寸要求高度最小为' + that.minHeight + 'px！')
        } else if (!imgWValid) {
          that.$message.error('图片尺寸要求宽度为' + that.imgWidth + 'px！')
        } else if (!imgHValid) {
          that.$message.error('图片尺寸要求高度为' + that.imgHeight + 'px！')
        }
        return Promise.reject()
      })
      return isSize
    },
    // 上传前对文件的大小进行判断
    beforeUpload(file) {
      this.fileInfo = file
      let hasAccept = true
      let isSize = true
      if (this.accept) {
        const fileExt = file.name.substring(file.name.lastIndexOf('.'))
        const list = this.accept.split(',')
        hasAccept = list.find(item => item === fileExt) ? true : false
        if (!hasAccept) {
          this.$message({
            message: '上传文件类型必须为' + this.accept,
            type: 'error'
          })
          return false
        }
      }
      if (this.alwaysCrop) {
        this.option.img = URL.createObjectURL(file)
        this.dialogVisible = true
        return false
      }
      if (this.imgWidth || this.imgHeight || this.minWidth || this.minHeight || this.isSquare) {
        isSize = this.sizeCheck(file)
      }
      return hasAccept && isSize
      // return isFileSize && hasAccept && isSize;
    },
    // 覆盖默认上传行为
    httpRequest(params) {
      const fd = new FormData()
      fd.append('file', params.file)
      upload(fd).then(res => {
        if (this.multiple) {
          this.$emit('setVal', res.image, 'add')
        } else {
          this.$emit('setVal', res.image)
        }
      })
    }
  }
}
</script>

<style lang="less">
.common-uploader {
  .el-upload__tip {
    margin-top: 0;
    color: #bbbbbb;
  }
	.el-upload__input{
		visibility: hidden;
	}
  .img_wrapper {
    position: relative;
    border: 1px solid #e6e6e6;

    &:hover .mask_tool {
      display: flex;
      align-items: center;
    }
  }

  .mask_tool {
		text-align: center;
    display: none;
    position: absolute;
    bottom: -15px;
    left: 0;
    right: 0;
    z-index: 3;
    height: 30px;
    color: #ffffff;
    background: rgba(0, 0, 0, 0.75);

    .el-divider {
      height: 18px;
      margin: 0;
    }
  }

  .photo_wrapper {
		display: flex;
		justify-content: justify-center;
		text-align: center;
    background: #ffffff;
    border: 1px solid #eeeeee;
    color: #999999;

    i {
			line-height: 95px;
      font-size: 30px;
      color: #cccccc;
			position: absolute;
			left: 30px;
			top:-10px;
    }

    span {
			position: absolute;
			top:10px;
			left: 20px;
			text-align: center;
      line-height: 105px;
    }
  }

  .mul_list .img_wrapper {
    margin-right: 10px;
    margin-bottom: 10px;
  }
}

.el-image-viewer__wrapper {
  z-index: 2090 !important;
}
.text-center{
	display: block;
	text-align: center;
}
</style>
